package config

import (
	"fmt"
	"github.com/go-redis/redis"
	"github.com/spf13/viper"
	"go-web2/app/common/mylog"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"strings"
	"time"
)

var (
	Config         *viper.Viper
	HTTPPort       int
	ReadTimeout    time.Duration
	WriteTimeout   time.Duration
	DB             *gorm.DB
	RedisConn      *redis.Client
	AuthHost       []string
	AllowCorsApi   string
	AllowedOrigins []string
	FilePath       string
)

func InitConfig() (*viper.Viper, error) {
	viper.SetConfigName("application") // 配置文件的文件名（不带扩展名）
	viper.SetConfigType("yaml")        // 配置文件的类型
	//viper.AddConfigPath("./app.common.config")    // 配置文件所在的路径，这里假设配置文件在项目根目录下的 app.common.config 文件夹中
	viper.AddConfigPath("./")   // 配置文件所在的路径，项目根目录下
	err := viper.ReadInConfig() // 读取配置文件
	if err != nil {
		return nil, err
	}
	Config = viper.GetViper()
	LoadServer()
	LoadMysql()
	LoadRedis()
	LoadIP()
	return Config, nil
}

func LoadServer() {
	HTTPPort = Config.GetInt("server.port")
	ReadTimeout = time.Duration(Config.GetInt("server.read_timeout")) * time.Second
	WriteTimeout = time.Duration(Config.GetInt("server.write_timeout")) * time.Second
	FilePath = Config.GetString("filePath")
}

type Writer struct{}

// 自定义的sql日志输出（到文件）
func (w Writer) Printf(format string, args ...interface{}) {
	msg := fmt.Sprintf(format, args...) + "\n"
	fmt.Println(msg)  // 打印到控制台
	mylog.LogOut(msg) // 输出到文件
}

func LoadMysql() {
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s",
		Config.Get("database.username"),
		Config.Get("database.password"),
		Config.Get("database.host"),
		Config.GetInt("database.port"),
		Config.Get("database.database"),
		Config.Get("database.timeout"))
	// 设置操作数据库的日志输出到文件
	mylogger := logger.New(
		Writer{},
		logger.Config{
			SlowThreshold: time.Second, // 慢 SQL 阈值
			LogLevel:      logger.Info, // Log level
			Colorful:      true,        // 允许彩色打印
		},
	)
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		// 跳过默认事务：为了确保数据一致性，GORM 会在事务里执行写入操作（创建、更新、删除）。如果没有这方面的要求，您可以在初始化时禁用它，这样可以获得60%的性能提升
		//SkipDefaultTransaction: true,
		//Logger: logger.Default.LogMode(logger.Info), // sql全局日志
		Logger: mylogger, // 使用自定义的日志输出
		NamingStrategy: schema.NamingStrategy{
			//TablePrefix:   "sys_",  // 表名前缀
			SingularTable: true, // 单数表名
			//NoLowerCase:   false, // 关闭小写转换
		},
	})
	if err != nil {
		fmt.Println("无法连接到MySQL :", err)
	}
	DB = db
}

func LoadRedis() {
	RedisConn = redis.NewClient(&redis.Options{
		Addr:     fmt.Sprintf("%s:%d", Config.Get("redis.host"), Config.GetInt("redis.port")),
		Password: Config.GetString("redis.password"),
	})
	if err := RedisConn.Ping().Err(); err != nil {
		fmt.Println("无法连接到redis")
	}
}

func LoadIP() {
	ips := Config.GetString("ip.auth_host")
	AuthHost = strings.Split(ips, ";")
	AllowCorsApi = Config.GetString("ip.allow_cors_api")
	origins := Config.GetString("ip.allowed_origins")
	AllowedOrigins = strings.Split(origins, ";")
}
